using System;
using System.Diagnostics;
using BepuUtilities;
using BepuPhysics;
using BepuPhysics.Collidables;
using BepuPhysics.Constraints;
using BepuUtilities.Collections;
using BepuUtilities.Memory;
#if MYCODE
using BepuUtilities.Vectors;
#else
using System.Numerics;
#endif
namespace Demos.Demos.Tanks
{
    /// <summary>
    /// 坦克实例的句柄和引用集。
    /// </summary>
    public struct Tank
    {
        /// <summary>
        /// 坦克主体的车身手柄。
        /// </summary>
        public BodyHandle Body;
        /// <summary>
        /// 坦克炮塔的车身手柄。
        /// </summary>
        public BodyHandle Turret;
        /// <summary>
        /// 坦克枪管的车身手柄。
        /// </summary>
        public BodyHandle Barrel;
        /// <summary>
        /// 转塔旋转伺服的约束手柄。
        /// </summary>
        public ConstraintHandle TurretServo;
        /// <summary>
        /// 滚筒俯仰伺服的约束手柄。
        /// </summary>
        public ConstraintHandle BarrelServo;
        /// <summary>
        /// 与油箱关联的所有轮体手柄的列表。
        /// </summary>
        public Buffer<BodyHandle> WheelHandles;
        /// <summary>
        /// 与坦克关联的所有约束句柄的列表。包括电机。
        /// </summary>
        public Buffer<ConstraintHandle> Constraints;
        /// <summary>
        /// 与左踏板驱动电机关联的约束控制柄列表。
        /// </summary>
        public Buffer<ConstraintHandle> LeftMotors;
        /// <summary>
        /// 与右踏板驱动电机关联的约束控制柄列表。
        /// </summary>
        public Buffer<ConstraintHandle> RightMotors;

        /// <summary>
        /// 将方向从主体局部空间变换到炮塔基础局部空间。用于计算瞄准角。
        /// </summary>
        Quaternion FromBodyLocalToTurretBasisLocal;
        /// <summary>
        /// 坦克局部空间中车身的方向。
        /// </summary>
        public Quaternion BodyLocalOrientation;
        /// <summary>
        /// 应在枪管本体的局部空间中创建抛射物的位置。
        /// </summary>
        Vector3 BarrelLocalProjectileSpawn;
        /// <summary>
        /// 枪管本体局部空间中的方向,投射物应沿该方向发射。
        /// </summary>
        Vector3 BarrelLocalDirection;
        /// <summary>
        /// 坦克发射的炮弹的速度。
        /// </summary>
        float ProjectileSpeed;
        /// <summary>
        /// 坦克发射的炮弹的惯性。
        /// </summary>
        BodyInertia ProjectileInertia;
        /// <summary>
        /// 坦克发射的炮弹的形状。
        /// </summary>
        TypedIndex ProjectileShape;

        // 我们缓存了马达描述,所以我们不需要重新计算基数。
        TwistServo BarrelServoDescription;
        TwistServo TurretServoDescription;

        public void SetSpeed(Simulation simulation, Buffer<ConstraintHandle> motors, float speed, float maximumForce)
        {
            // 这样可以一次设置电机的所有属性;可以创建自定义描述,如果您发现这样做比较昂贵,则只分配属性的一个子集。
            var motorDescription = new AngularAxisMotor
            {
                // 假设轮子是以明显的方式定向的圆柱体。
                LocalAxisA = new Vector3(0, -1, 0),
                Settings = new MotorSettings(maximumForce, 1e-6f),
                TargetVelocity = speed
            };
            for (int i = 0; i < motors.Length; ++i)
            {
                simulation.Solver.ApplyDescription(motors[i], ref motorDescription);
            }
        }


        /// <summary>
        /// 根据坦克的当前姿势计算瞄准给定方向所需的旋转角度和俯仰角度。
        /// </summary>
        /// <param name="Simulation">包含坦克的模拟。</param>
        /// <param name="aimDirection">目标方向。</param>
        /// <return>指向给定方向的旋转和俯仰角度。</return>
        public (float targetSwivelAngle, float targetPitchAngle) ComputeTurretAngles(Simulation simulation, in Vector3 aimDirection)
        {
            // 将瞄准方向分解为转塔和桶形伺服的目标角度。
            // 首先,我们需要计算参照系,并将目标方向转换到坦克的局部空间。
            // Aim Direction*Inverse(Body.Pose.Orientation)*Tank.LocalBodyPose.Orientation*Inverse(Tank.TurretBasis)
            QuaternionEx.ConcatenateWithoutOverlap(QuaternionEx.Conjugate(simulation.Bodies.GetBodyReference(Body).Pose.Orientation), FromBodyLocalToTurretBasisLocal, out var toTurretBasis);
            // 转塔基点中的-Z沿旋转和俯仰的0角度方向。
            // +Y是俯仰的90度。
            // 旋转时+X为90度。
            // 我们先计算旋转角度。
            QuaternionEx.TransformWithoutOverlap(aimDirection, toTurretBasis, out var aimDirectionInTurretBasis);
            var targetSwivelAngle = MathF.Atan2(aimDirectionInTurretBasis.X, -aimDirectionInTurretBasis.Z);

            // 根据+Y轴和从目标旋转角度创建的轴测量炮管俯仰。
            var targetPitchAngle = MathF.Asin(MathF.Max(-1f, MathF.Min(1f, -aimDirectionInTurretBasis.Y)));
            return (targetSwivelAngle, targetPitchAngle);
        }

        /// <summary>
        /// 将目标旋转和俯仰角度应用于炮塔的伺服。
        /// </summary>
        /// <param name="Simulation">包含坦克的模拟。</param>
        /// <param name="targetSwivelangle">转塔的目标旋转角度。</param>
        /// <param name="targetPitchangle">桶的目标俯仰角。</param>
        public void SetAim(Simulation simulation, float targetSwivelAngle, float targetPitchAngle)
        {
            var turretDescription = TurretServoDescription;
            turretDescription.TargetAngle = targetSwivelAngle;
            simulation.Solver.ApplyDescription(TurretServo, ref turretDescription);
            var barrelDescription = BarrelServoDescription;
            barrelDescription.TargetAngle = targetPitchAngle;
            simulation.Solver.ApplyDescription(BarrelServo, ref barrelDescription);

        }

        /// <summary>
        /// 计算桶指向的方向。
        /// </summary>
        /// <param name="Simulation">包含坦克的模拟。</param>
        /// <param name="barrelDirection">桶指向的方向。</param>
        public void ComputeBarrelDirection(Simulation simulation, out Vector3 barrelDirection)
        {
            QuaternionEx.Transform(BarrelLocalDirection, simulation.Bodies.GetBodyReference(Barrel).Pose.Orientation, out barrelDirection);
        }

        /// <summary>
        /// 发射一枚炮弹。
        /// </summary>
        /// <param name="Simulation">包含坦克的模拟。</param>
        /// <param name="bodyProperties">要在其中分配投射物属性的主体属性。</param>
        /// <return>创建的投射体的句柄。</return>
        public BodyHandle Fire(Simulation simulation, CollidableProperty<TankDemoBodyProperties> bodyProperties)
        {
            var barrel = simulation.Bodies.GetBodyReference(Barrel);
            ref var barrelPose = ref barrel.Pose;
            RigidPose.Transform(BarrelLocalProjectileSpawn, barrelPose, out var projectileSpawn);
            QuaternionEx.Transform(BarrelLocalDirection, barrelPose.Orientation, out var barrelDirection);
            var projectileHandle = simulation.Bodies.Add(BodyDescription.CreateDynamic(projectileSpawn, new BodyVelocity(barrelDirection * ProjectileSpeed + barrel.Velocity.Linear), ProjectileInertia,
                // 投射物移动得相当快,所以我们将使用连续碰撞检测。
                new CollidableDescription(ProjectileShape, 0.1f, ContinuousDetectionSettings.Continuous(1e-3f, 1e-3f)), new BodyActivityDescription(0.01f)));
            ref var projectileProperties = ref bodyProperties.Allocate(projectileHandle);
            projectileProperties.Friction = 1f;
            // 防止炮弹与射击坦克相撞。
            projectileProperties.Filter = new SubgroupCollisionFilter(Body.Value);
            projectileProperties.Filter.CollidableSubgroups = 0;
            projectileProperties.Filter.SubgroupMembership = 0;
            projectileProperties.Projectile = true;

            barrel.Awake = true;
            barrel.ApplyLinearImpulse(barrelDirection * -ProjectileSpeed / ProjectileInertia.InverseMass);
            return projectileHandle;
        }

        static BodyHandle CreateWheel(Simulation simulation, CollidableProperty<TankDemoBodyProperties> properties, in RigidPose tankPose, in RigidPose bodyLocalPose,
            TypedIndex wheelShape, BodyInertia wheelInertia, float wheelFriction, BodyHandle bodyHandle, ref SubgroupCollisionFilter bodyFilter, in Vector3 bodyToWheelSuspension, float suspensionLength,
            in SpringSettings suspensionSettings, in Quaternion localWheelOrientation,
            ref QuickList<BodyHandle> wheelHandles, ref QuickList<ConstraintHandle> constraints, ref QuickList<ConstraintHandle> motors)
        {
            RigidPose wheelPose;
            QuaternionEx.TransformUnitX(localWheelOrientation, out var suspensionDirection);
            RigidPose.Transform(bodyToWheelSuspension + suspensionDirection * suspensionLength, tankPose, out wheelPose.Position);
            QuaternionEx.ConcatenateWithoutOverlap(localWheelOrientation, tankPose.Orientation, out wheelPose.Orientation);

            var wheelHandle = simulation.Bodies.Add(BodyDescription.CreateDynamic(wheelPose, wheelInertia, new CollidableDescription(wheelShape, 0.1f), new BodyActivityDescription(0.01f)));
            wheelHandles.AllocateUnsafely() = wheelHandle;

            // 我们需要一个直线轴伺服系统来充当悬挂弹簧,把轮子往下推。
            constraints.AllocateUnsafely() = simulation.Solver.Add(bodyHandle, wheelHandle, new LinearAxisServo
            {
                LocalPlaneNormal = suspensionDirection,
                TargetOffset = suspensionLength,
                LocalOffsetA = bodyToWheelSuspension,
                LocalOffsetB = default,
                ServoSettings = ServoSettings.Default,
                SpringSettings = suspensionSettings
            });
            // PointOnLineServo使轮子保持在固定的轨道上。请注意,它根本不约束控制盘的角度行为。
            constraints.AllocateUnsafely() = simulation.Solver.Add(bodyHandle, wheelHandle, new PointOnLineServo
            {
                LocalDirection = suspensionDirection,
                LocalOffsetA = bodyToWheelSuspension,
                LocalOffsetB = default,
                ServoSettings = ServoSettings.Default,
                SpringSettings = new SpringSettings(30, 1)
            });
            // 角度部件由铰链处理。请注意,我们在此仅使用铰链约束的角度组件-PointOnLineServo处理线性自由度。
            // 我们假设轮子是圆柱形的。很安全的打赌。圆柱体绕其局部Y轴滚动,因此马达将沿该轴运动。
            QuaternionEx.TransformUnitY(localWheelOrientation, out var wheelRotationAxis);
            constraints.AllocateUnsafely() = simulation.Solver.Add(bodyHandle, wheelHandle, new AngularHinge
            {
                LocalHingeAxisA = QuaternionEx.Transform(wheelRotationAxis, QuaternionEx.Conjugate(bodyLocalPose.Orientation)),
                LocalHingeAxisB = new Vector3(0, 1, 0),
                SpringSettings = new SpringSettings(30, 1)
            });
            // 我们需要一个速度马达才能真正使坦克移动。
            var motorHandle = simulation.Solver.Add(wheelHandle, bodyHandle, new AngularAxisMotor
            {
                // (这些都是现在更新的时候在飞翔技术上设置的,但是自定义的约束描述只能设置设置和目标速度,
                // 保留LocalAxisA不变,因此我们将继续并将其设置为一个合理的值。)
                LocalAxisA = new Vector3(0, 1, 0),
                Settings = default,
                TargetVelocity = default
            });
            motors.AllocateUnsafely() = motorHandle;
            constraints.AllocateUnsafely() = motorHandle;
            ref var wheelProperties = ref properties.Allocate(wheelHandle);
            wheelProperties = new TankDemoBodyProperties { Filter = new SubgroupCollisionFilter(bodyHandle.Value, 3), Friction = wheelFriction, TankPart = true };
            // 轮子不需要在车身或彼此之间进行测试。
            SubgroupCollisionFilter.DisableCollision(ref wheelProperties.Filter, ref bodyFilter);
            SubgroupCollisionFilter.DisableCollision(ref wheelProperties.Filter, ref wheelProperties.Filter);
            return wheelHandle;
        }

        static ref SubgroupCollisionFilter CreatePart(Simulation simulation, in TankPartDescription part, RigidPose pose, CollidableProperty<TankDemoBodyProperties> properties, out BodyHandle handle)
        {
            RigidPose.MultiplyWithoutOverlap(part.Pose, pose, out var bodyPose);
            handle = simulation.Bodies.Add(BodyDescription.CreateDynamic(bodyPose, part.Inertia, new CollidableDescription(part.Shape, 0.1f), new BodyActivityDescription(0.01f)));
            ref var partProperties = ref properties.Allocate(handle);
            partProperties = new TankDemoBodyProperties { Friction = part.Friction, TankPart = true };
            return ref partProperties.Filter;
        }

        /// <summary>
        /// 根据提供的坦克描述创建坦克。
        /// </summary>
        /// <param name="Simulation">要将坦克添加到的模拟。</param>
        /// <param name="properties">设置为存储个人信息的属性。</param>
        /// <param name="pool">从中分配坦克资源的缓冲池。</param>
        /// <param name="pose">坦克的姿势。</param>
        /// <param name="description">坦克的描述。</param>
        /// <return>包含对模拟坦克部件的引用的Tank实例。</return>
        public static Tank Create(Simulation simulation, CollidableProperty<TankDemoBodyProperties> properties, BufferPool pool, in RigidPose pose, in TankDescription description)
        {
            var wheelHandles = new QuickList<BodyHandle>(description.WheelCountPerTread * 2, pool);
            var constraints = new QuickList<ConstraintHandle>(description.WheelCountPerTread * 2 * 6 + 4, pool);
            var leftMotors = new QuickList<ConstraintHandle>(description.WheelCountPerTread, pool);
            var rightMotors = new QuickList<ConstraintHandle>(description.WheelCountPerTread, pool);
            Tank tank;
            ref var bodyFilter = ref CreatePart(simulation, description.Body, pose, properties, out tank.Body);
            ref var turretFilter = ref CreatePart(simulation, description.Turret, pose, properties, out tank.Turret);
            ref var barrelFilter = ref CreatePart(simulation, description.Barrel, pose, properties, out tank.Barrel);
            // 使用坦克的车身控制柄作为碰撞过滤器的组ID。
            bodyFilter = new SubgroupCollisionFilter(tank.Body.Value, 0);
            turretFilter = new SubgroupCollisionFilter(tank.Body.Value, 1);
            barrelFilter = new SubgroupCollisionFilter(tank.Body.Value, 2);
            SubgroupCollisionFilter.DisableCollision(ref bodyFilter, ref turretFilter);
            SubgroupCollisionFilter.DisableCollision(ref turretFilter, ref barrelFilter);

            Matrix3x3.CreateFromQuaternion(description.TurretBasis, out var turretBasis);

            // 将炮塔连接到机身上。
            QuaternionEx.Transform(turretBasis.Y, QuaternionEx.Conjugate(description.Body.Pose.Orientation), out var bodyLocalSwivelAxis);
            QuaternionEx.Transform(turretBasis.Y, QuaternionEx.Conjugate(description.Turret.Pose.Orientation), out var turretLocalSwivelAxis);
            RigidPose.TransformByInverse(description.TurretAnchor, description.Body.Pose, out var bodyLocalTurretAnchor);
            RigidPose.TransformByInverse(description.TurretAnchor, description.Turret.Pose, out var turretLocalTurretAnchor);
            constraints.AllocateUnsafely() = simulation.Solver.Add(tank.Body, tank.Turret,
                new Hinge
                {
                    LocalHingeAxisA = bodyLocalSwivelAxis,
                    LocalHingeAxisB = turretLocalSwivelAxis,
                    LocalOffsetA = bodyLocalTurretAnchor,
                    LocalOffsetB = turretLocalTurretAnchor,
                    SpringSettings = new SpringSettings(30, 1)
                });
            // 扭转伺服可能看起来像是一个奇怪的选择来控制1个角度的自由度,但类似伺服的控制超过1个自由度需要一个测量基础来解释目标角度。
            // 因此就有了明显的复杂性。
            Matrix3x3 turretSwivelBasis;
            turretSwivelBasis.Z = -turretBasis.Y;
            turretSwivelBasis.X = -turretBasis.Z;
            turretSwivelBasis.Y = turretBasis.X;
            Debug.Assert(turretSwivelBasis.Determinant() > 0.999f && turretSwivelBasis.Determinant() < 1.0001f, "The turret swivel axis and forward axis should be perpendicular and unit length.");
            QuaternionEx.CreateFromRotationMatrix(turretSwivelBasis, out var turretSwivelBasisQuaternion);
            QuaternionEx.ConcatenateWithoutOverlap(turretSwivelBasisQuaternion, QuaternionEx.Conjugate(description.Body.Pose.Orientation), out var bodyLocalTurretBasis);
            QuaternionEx.ConcatenateWithoutOverlap(turretSwivelBasisQuaternion, QuaternionEx.Conjugate(description.Turret.Pose.Orientation), out var turretLocalTurretBasis);
            tank.TurretServoDescription = new TwistServo
            {
                LocalBasisA = bodyLocalTurretBasis,
                LocalBasisB = turretLocalTurretBasis,
                SpringSettings = description.TurretSpring,
                ServoSettings = description.TurretServo
            };
            tank.TurretServo = simulation.Solver.Add(tank.Body, tank.Turret, tank.TurretServoDescription);
            constraints.AllocateUnsafely() = tank.TurretServo;

            // 将枪管连接到转塔上。
            QuaternionEx.Transform(turretBasis.X, QuaternionEx.Conjugate(description.Turret.Pose.Orientation), out var turretLocalPitchAxis);
            QuaternionEx.Transform(turretBasis.X, QuaternionEx.Conjugate(description.Barrel.Pose.Orientation), out var barrelLocalPitchAxis);
            RigidPose.TransformByInverse(description.BarrelAnchor, description.Turret.Pose, out var turretLocalBarrelAnchor);
            RigidPose.TransformByInverse(description.BarrelAnchor, description.Barrel.Pose, out var barrelLocalBarrelAnchor);
            constraints.AllocateUnsafely() = simulation.Solver.Add(tank.Turret, tank.Barrel,
                new Hinge
                {
                    LocalHingeAxisA = turretLocalPitchAxis,
                    LocalHingeAxisB = barrelLocalPitchAxis,
                    LocalOffsetA = turretLocalBarrelAnchor,
                    LocalOffsetB = barrelLocalBarrelAnchor,
                    SpringSettings = new SpringSettings(30, 1)
                });
            // 扭转伺服可能看起来像是一个奇怪的选择来控制1个角度的自由度,但类似伺服的控制超过1个自由度需要一个测量基础来解释目标角度。
            // 因此就有了明显的复杂性。
            Matrix3x3 barrelPitchBasis;
            barrelPitchBasis.Z = -turretBasis.X;
            barrelPitchBasis.X = -turretBasis.Z;
            barrelPitchBasis.Y = -turretBasis.Y;
            Debug.Assert(barrelPitchBasis.Determinant() > 0.999f && barrelPitchBasis.Determinant() < 1.0001f, "The barrel axis and forward axis should be perpendicular and unit length.");
            QuaternionEx.CreateFromRotationMatrix(barrelPitchBasis, out var barrelPitchBasisQuaternion);
            QuaternionEx.ConcatenateWithoutOverlap(barrelPitchBasisQuaternion, QuaternionEx.Conjugate(description.Turret.Pose.Orientation), out var turretLocalBarrelBasis);
            QuaternionEx.ConcatenateWithoutOverlap(barrelPitchBasisQuaternion, QuaternionEx.Conjugate(description.Barrel.Pose.Orientation), out var barrelLocalBarrelBasis);
            tank.BarrelServoDescription = new TwistServo
            {
                LocalBasisA = turretLocalBarrelBasis,
                LocalBasisB = barrelLocalBarrelBasis,
                SpringSettings = description.BarrelSpring,
                ServoSettings = description.BarrelServo
            };
            tank.BarrelServo = simulation.Solver.Add(tank.Turret, tank.Barrel, tank.BarrelServoDescription);
            constraints.AllocateUnsafely() = tank.BarrelServo;

            QuaternionEx.TransformUnitY(description.WheelOrientation, out var wheelAxis);
            QuaternionEx.TransformUnitZ(description.WheelOrientation, out var treadDirection);
            var treadStart = description.TreadSpacing * (description.WheelCountPerTread - 1) * -0.5f;
            BodyHandle previousLeftWheelHandle = default, previousRightWheelHandle = default;
            for (int i = 0; i < description.WheelCountPerTread; ++i)
            {
                var wheelOffsetFromTread = treadDirection * (treadStart + i * description.TreadSpacing);
                var rightWheelHandle = CreateWheel(simulation, properties, pose, description.Body.Pose,
                    description.WheelShape, description.WheelInertia, description.WheelFriction, tank.Body, ref properties[tank.Body].Filter,
                    description.RightTreadOffset + wheelOffsetFromTread - description.Body.Pose.Position,
                    description.SuspensionLength, description.SuspensionSettings, description.WheelOrientation,
                    ref wheelHandles, ref constraints, ref rightMotors);
                var leftWheelHandle = CreateWheel(simulation, properties, pose, description.Body.Pose,
                    description.WheelShape, description.WheelInertia, description.WheelFriction, tank.Body, ref properties[tank.Body].Filter,
                    description.LeftTreadOffset + wheelOffsetFromTread - description.Body.Pose.Position,
                    description.SuspensionLength, description.SuspensionSettings, description.WheelOrientation,
                    ref wheelHandles, ref constraints, ref leftMotors);

                if (i >= 1)
                {
                    // 将踏板上的车轮相互连接以分配驱动力。
                    // 马达将始终以0速度为目标。车轮方向将允许彼此漂移。
                    // (如果您不想允许漂移,您可以使用AngularServo或TwistServo。AngularServo约束所有3个自由度,但对于这些目的来说,这是很好的。)
                    var motorDescription = new AngularAxisMotor { LocalAxisA = new Vector3(0, 1, 0), Settings = new MotorSettings(float.MaxValue, 1e-4f) };
                    constraints.AllocateUnsafely() = simulation.Solver.Add(previousLeftWheelHandle, leftWheelHandle, ref motorDescription);
                    constraints.AllocateUnsafely() = simulation.Solver.Add(previousRightWheelHandle, rightWheelHandle, ref motorDescription);
                }
                previousLeftWheelHandle = leftWheelHandle;
                previousRightWheelHandle = rightWheelHandle;

            }

            tank.WheelHandles = wheelHandles.Span.Slice(wheelHandles.Count);
            tank.Constraints = constraints.Span.Slice(constraints.Count);
            tank.LeftMotors = leftMotors.Span.Slice(leftMotors.Count);
            tank.RightMotors = rightMotors.Span.Slice(rightMotors.Count);

            // 瞄准时,我们把瞄准方向转化为炮塔基础。
            // aimDirectionInTurretBasis=worldAimDirection*Inverse(body.Pose.Orientation)*description ption.Body.Pose.Orientation*Inverse(description(description ption.TurretBasis)),因此我们预计算并缓存：
            // FromBodyLocalToTurretBasisLocal=Description.Body.Pose.Orientation*Inversion(Description.TurretBasis)
            QuaternionEx.ConcatenateWithoutOverlap(description.Body.Pose.Orientation, QuaternionEx.Conjugate(description.TurretBasis), out tank.FromBodyLocalToTurretBasisLocal);
            tank.BodyLocalOrientation = description.Body.Pose.Orientation;
            tank.BarrelLocalProjectileSpawn = description.BarrelLocalProjectileSpawn;
            QuaternionEx.Transform(-turretBasis.Z, QuaternionEx.Conjugate(description.Barrel.Pose.Orientation), out tank.BarrelLocalDirection);
            tank.ProjectileInertia = description.ProjectileInertia;
            tank.ProjectileShape = description.ProjectileShape;
            tank.ProjectileSpeed = description.ProjectileSpeed;
            return tank;
        }

        void ClearBodyProperties(ref TankDemoBodyProperties properties)
        {
            // 爆炸后,所有的坦克部件都会相互碰撞,我们不应该再把这些碎片标记为活坦克的一部分。
            properties.Filter = new SubgroupCollisionFilter(properties.Filter.GroupId);
            properties.TankPart = false;
        }

        public void Explode(Simulation simulation, CollidableProperty<TankDemoBodyProperties> properties, BufferPool pool)
        {
            // 当坦克爆炸时,我们只需移除所有绑定约束,让它解体并重置车身属性即可。
            for (int i = 0; i < WheelHandles.Length; ++i)
            {
                ClearBodyProperties(ref properties[WheelHandles[i]]);
            }
            ClearBodyProperties(ref properties[Body]);
            ClearBodyProperties(ref properties[Turret]);
            ClearBodyProperties(ref properties[Barrel]);
            var turret = simulation.Bodies.GetBodyReference(Turret);
            turret.Awake = true;
            turret.Velocity.Linear += new Vector3(0, 10, 0);
            for (int i = 0; i < Constraints.Length; ++i)
            {
                simulation.Solver.Remove(Constraints[i]);
            }
            pool.Return(ref WheelHandles);
            pool.Return(ref Constraints);
            pool.Return(ref LeftMotors);
            pool.Return(ref RightMotors);
        }

    }
}
